@a = global [3 x [3 x float]] [[3 x float] [float 1.500000e+00, float 2.000000e+00, float 3.000000e+00], [3 x float] [float 3.000000e+00, float 0.000000e+00, float 1.000000e+00], [3 x float] [float 0x3FF19999A0000000, float 3.000000e+00, float 0x4002666660000000]]
@c = global [3 x [3 x float]] zeroinitializer
@.str1 = constant [4 x i8] c"%f \00"
@.str2 = constant [2 x i8] c"\0A\00"

declare i32 @printf(ptr,...)
declare i32 @__isoc99_scanf(ptr,...)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg)

define void @matrix_mul(ptr %aa, ptr %b, ptr %c,i32 %n) {
    %ptri=alloca i32
    %ptrj=alloca i32
    %ptrk=alloca i32
    store i32 0, ptr %ptri
    br label %WHILECOND
    WHILECOND:
        %i=load i32, ptr %ptri
        %cmp=icmp slt i32 %i, %n
        br i1 %cmp, label %WHILEBODY, label %WHILEEND
    WHILEBODY:
        store i32 0,ptr %ptrj
        br label %FORCOND1
        FORCOND1:
            %j=load i32, ptr %ptrj
            %cmp_1=icmp slt i32 %j, %n
            br i1 %cmp_1, label %FORBODY1, label %FOREND1
        FORBODY1:
            store i32 0, ptr %ptrk
            br label %FORCOND2
            FORCOND2:
                %k=load i32, ptr %ptrk
                %cmp_2=icmp slt i32 %k, %n
                br i1 %cmp_2, label %FORBODY2, label %FOREND2
            FORBODY2:
                %aikptr=getelementptr [3 x [3 x float]], ptr %aa, i32 0, i32 %i, i32 %k
                %aikval=load float, ptr %aikptr

                %bkjptr=getelementptr [3 x [3 x float]], ptr %b, i32 0, i32 %k, i32 %j
                %bkjval=load float, ptr %bkjptr

                %cijptr=getelementptr [3 x [3 x float]], ptr %c, i32 0, i32 %i, i32 %j
                %cijval=load float, ptr %cijptr

                %abmul=fmul float %aikval, %bkjval
                %cijval_1=fadd float %cijval, %abmul
            
                store float %cijval_1, ptr %cijptr

                %kval=load i32, ptr %ptrk
                %kval_1=add i32 %kval, 1
                store i32 %kval_1, ptr %ptrk
                br label %FORCOND2
            FOREND2:
            %jval=load i32,ptr %ptrj
            %jval_1=add i32 %jval, 1
            store i32 %jval_1,ptr %ptrj
            br label %FORCOND1
        FOREND1:
        %ival=load i32, ptr %ptri
        %ival_1=add i32 %ival, 1
        store i32 %ival_1, ptr %ptri
        br label %WHILECOND
    WHILEEND:
    ret void
}

define i32 @main(){
    %n=alloca i32
    %b=alloca [3 x [3 x float]]
    call void @llvm.memset.p0.i64(ptr %b, i8 0, i64 36, i1 false)
    ;make b filled with{{1.3 , 2.5 , 3.3},{1.5},{2}};
    %b00ptr=getelementptr [3 x [3 x float]], ptr %b, i32 0, i32 0, i32 0
    %b01ptr=getelementptr [3 x [3 x float]], ptr %b, i32 0, i32 0, i32 1
    %b02ptr=getelementptr [3 x [3 x float]], ptr %b, i32 0, i32 0, i32 2
    %b10ptr=getelementptr [3 x [3 x float]], ptr %b, i32 0, i32 1, i32 0
    %b20ptr=getelementptr [3 x [3 x float]], ptr %b, i32 0, i32 2, i32 0

    store float 0x3FF4CCCCC0000000, ptr %b00ptr
    store float 2.500000e+00, ptr %b01ptr
    store float 0x400A666660000000, ptr %b02ptr
    store float 1.500000e+00, ptr %b10ptr
    store float 2.000000e+00, ptr %b20ptr

    store i32 3, ptr %n
    %nval=load i32, ptr %n

    call void @matrix_mul(ptr @a, ptr %b, ptr @c,i32 %nval)

    %i=alloca i32
    store i32 0, ptr %i
    br label %FORCOND
    FORCOND:
        %ival=load i32, ptr %i
        %cmp=icmp slt i32 %ival, %nval
        br i1 %cmp, label %FORBODY, label %FOREND
    FORBODY:
        %j=alloca i32
        store i32 0, ptr %j
        br label %FORCOND1
        FORCOND1:
            %jval=load i32, ptr %j
            %cmp_1=icmp slt i32 %jval, %nval
            br i1 %cmp_1, label %FORBODY1, label %FOREND1
        FORBODY1:
            %cijptr=getelementptr [3 x [3 x float]], ptr @c, i32 0, i32 %ival, i32 %jval
            %cijval=load float, ptr %cijptr
            %cijDoubleVal=fpext float %cijval to double
            call i32 @printf(ptr @.str1, double %cijDoubleVal)
            %jval_1=load i32, ptr %j
            %jval_2=add i32 %jval_1, 1
            store i32 %jval_2, ptr %j
            br label %FORCOND1
        FOREND1:
        call i32 @printf(ptr @.str2)
        %ival_1=load i32, ptr %i
        %ival_2=add i32 %ival_1, 1
        store i32 %ival_2, ptr %i
        br label %FORCOND
    FOREND:

    ret i32 0
}